"""
分布式锁管理API
用于监控和管理K8s集群中的分布式锁
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime

from app.database.base import get_db
from app.core.auth import get_current_user
from app.models.user import User
from app.services.distributed_lock import DistributedLock
from pydantic import BaseModel


# Pydantic模型
class LockInfo(BaseModel):
    """锁信息响应模型"""
    lock_key: str
    lock_token: str
    node_id: str
    expire_time: datetime
    created_at: datetime
    is_expired: bool
    
    class Config:
        from_attributes = True


class LockListResponse(BaseModel):
    """锁列表响应模型"""
    items: List[LockInfo]
    total: int


class NodeInfo(BaseModel):
    """节点信息响应模型"""
    node_id: str
    lock_count: int
    locks: List[str]


router = APIRouter(prefix="/distributed-locks", tags=["分布式锁管理"])


@router.get("/", response_model=LockListResponse)
async def get_locks(
    expired: Optional[bool] = Query(None, description="过滤过期锁"),
    node_id: Optional[str] = Query(None, description="节点ID"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取分布式锁列表"""
    lock_service = DistributedLock(db)
    
    try:
        # 构建查询条件
        conditions = []
        if node_id:
            conditions.append(f"node_id = '{node_id}'")
        
        if expired is not None:
            if expired:
                conditions.append("expire_time < NOW()")
            else:
                conditions.append("expire_time >= NOW()")
        
        where_clause = " AND ".join(conditions) if conditions else "1=1"
        
        # 查询锁信息
        query = f"""
            SELECT lock_key, lock_token, node_id, expire_time, created_at,
                   (expire_time < NOW()) as is_expired
            FROM distributed_locks 
            WHERE {where_clause}
            ORDER BY created_at DESC
        """
        
        result = db.execute(query)
        locks = []
        
        for row in result.fetchall():
            locks.append(LockInfo(
                lock_key=row[0],
                lock_token=row[1],
                node_id=row[2],
                expire_time=row[3],
                created_at=row[4],
                is_expired=row[5]
            ))
        
        return LockListResponse(
            items=locks,
            total=len(locks)
        )
        
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取锁列表失败: {str(e)}"
        )


@router.get("/{lock_key}", response_model=LockInfo)
async def get_lock_info(
    lock_key: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取指定锁的详细信息"""
    lock_service = DistributedLock(db)
    
    lock_info = lock_service.get_lock_info(lock_key)
    if not lock_info:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="锁不存在"
        )
    
    return LockInfo(**lock_info)


@router.delete("/{lock_key}")
async def force_release_lock(
    lock_key: str,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """强制释放指定的锁（仅管理员操作）"""
    try:
        result = db.execute(f"""
            DELETE FROM distributed_locks 
            WHERE lock_key = '{lock_key}'
        """)
        
        db.commit()
        
        if result.rowcount > 0:
            return {"message": f"锁 {lock_key} 已强制释放"}
        else:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="锁不存在"
            )
            
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"强制释放锁失败: {str(e)}"
        )


@router.delete("/expired/cleanup")
async def cleanup_expired_locks(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """清理所有过期的锁"""
    lock_service = DistributedLock(db)
    
    try:
        result = db.execute("""
            DELETE FROM distributed_locks 
            WHERE expire_time < NOW()
        """)
        
        db.commit()
        
        return {
            "message": f"已清理 {result.rowcount} 个过期锁",
            "cleaned_count": result.rowcount
        }
        
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"清理过期锁失败: {str(e)}"
        )


@router.get("/nodes/status", response_model=List[NodeInfo])
async def get_node_status(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取各节点的锁持有状态"""
    try:
        result = db.execute("""
            SELECT node_id, COUNT(*) as lock_count, 
                   ARRAY_AGG(lock_key) as lock_keys
            FROM distributed_locks 
            WHERE expire_time >= NOW()
            GROUP BY node_id
            ORDER BY lock_count DESC
        """)
        
        nodes = []
        for row in result.fetchall():
            nodes.append(NodeInfo(
                node_id=row[0],
                lock_count=row[1],
                locks=row[2] or []
            ))
        
        return nodes
        
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取节点状态失败: {str(e)}"
        )


@router.get("/statistics/summary")
async def get_lock_statistics(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """获取分布式锁统计信息"""
    try:
        # 总锁数
        total_locks = db.execute("""
            SELECT COUNT(*) FROM distributed_locks
        """).scalar()
        
        # 活跃锁数
        active_locks = db.execute("""
            SELECT COUNT(*) FROM distributed_locks 
            WHERE expire_time >= NOW()
        """).scalar()
        
        # 过期锁数
        expired_locks = db.execute("""
            SELECT COUNT(*) FROM distributed_locks 
            WHERE expire_time < NOW()
        """).scalar()
        
        # 节点数
        node_count = db.execute("""
            SELECT COUNT(DISTINCT node_id) FROM distributed_locks
        """).scalar()
        
        # 最近1小时创建的锁
        recent_locks = db.execute("""
            SELECT COUNT(*) FROM distributed_locks 
            WHERE created_at >= NOW() - INTERVAL '1 hour'
        """).scalar()
        
        return {
            "total_locks": total_locks,
            "active_locks": active_locks,
            "expired_locks": expired_locks,
            "node_count": node_count,
            "recent_locks_1h": recent_locks,
            "timestamp": datetime.now()
        }
        
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取统计信息失败: {str(e)}"
        )